#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2024 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Function: check whether include files for innerapi is changed
"""
import os
import json

class Part:
    def __init__(self, name, path, project, files, support_indep, innerapi_changed):
        self.name = name # 部件名
        self.path = path # 部件路径
        self.project = project # 所属项目
        self.files = files # 修改文件列表
        self.support_indep = support_indep # 是否支持独立编译
        self.innerapi_changed = innerapi_changed # 是否涉及InnerAPI变更


def read_data_json():
    """ data.json
    "indep_surpport_status": {
        "syscap_codec": true,
        "cares" : true
    },
    "project_info": {
    "developtools_syscap_codec": {
        "syscap_codec": "developtools/syscap_codec"
    },
    "third_party_cares": {
        "cares": "third_party/cares"
    }
    },
    "file_list": {
        "developtools_syscap_codec": [
            "src/common_method.c"
        ]
    }
    """
    with open("data.json", "r") as f:
        data = json.load(f)
        project_modified_files = data.get("file_list", {})
        project_dict = data.get("project_info", {})
        indep_surpport_status = data.get("indep_surpport_status")
        parts_info = dict()
        for project in project_dict.keys():
            for part_name in project_dict[project]:
                parts_info[part_name] = dict()
                parts_info[part_name]["path"] = project_dict[project][part_name]
                parts_info[part_name]["project"] = project
                parts_info[part_name]["support_indep"] = indep_surpport_status.get(project, False)
    return parts_info, project_modified_files
    


def read_bundle_json(bundle_json_path) -> dict:
    with open(bundle_json_path, "r") as f:
        bundle_json = json.load(f)
    return bundle_json


def get_part_innerkits(bundle_json) -> list:
    inner_kit_names = []
    try:
        inner_kits = bundle_json["component"]["build"]["inner_kits"]
    except KeyError:
        inner_kits = []
    for kit in inner_kits:
        inner_kit_names.append(kit.get("name"))
    return inner_kit_names


def get_public_include(kit_name, bundle_json, args) -> set:
    part_name = bundle_json["component"]["name"]
    subsystem = bundle_json["component"]["subsystem"]
    destPath = bundle_json["segment"]["destPath"]
    include_dirs = []
    module_file_name = kit_name.split(":")[1]
    if "(" in module_file_name:
        module_file_name = module_file_name[:module_file_name.index("(")]
    ohos_root = os.path.join("./", "../")
    module_file_path = os.path.join(ohos_root, "out", "rk3568", subsystem, part_name, "publicinfo", f"{module_file_name}.json")
    with open(module_file_path, "r") as f:
        module_info = json.load(f)
    public_configs = module_info.get("public_configs", [])
    for config in public_configs:
        include_dirs.extend(config["include_dirs"])
    for index, include_dir in enumerate(include_dirs):
        include_dir = include_dir.split(destPath)[-1][1:]
        include_dirs[index] = include_dir
    include_dirs = set(include_dirs)
    return include_dirs


def check_file_changed(include_dirs, file_list) -> bool:
    for file in file_list:
        suffix = os.path.splitext(file)[-1]
        for include in include_dirs:
            if file.startswith(include) and suffix in (".h", ".hpp", ".hxx"):
                return True
    return False

def check_part(part_name, basic_info, project_modified_files, args):
    part_path = basic_info["path"]
    project_name = basic_info["project"]
    modified_files = project_modified_files.get(project_name, [])
    support_indep = basic_info["support_indep"]
    ohos_root = os.path.join("./", "../")
    bundle_json_path = os.path.join(ohos_root, part_path, "bundle.json")
    bundle_json =read_bundle_json(bundle_json_path)
    inner_kits_names = get_part_innerkits(bundle_json)
    for inner_kit in inner_kits_names:
        public_include_dirs = get_public_include(inner_kit, bundle_json, args)
        is_changed = check_file_changed(public_include_dirs, modified_files)
        if is_changed:
            part = Part(part_name, part_path, project_name, modified_files, support_indep, True)
            return part
    part = Part(part_name, part_path, project_name, modified_files, support_indep, False)
    return part
    
def check_build_parts(args) -> dict:
    innerapi_change_status = dict()
    parts_basic_info, project_modified_files = read_data_json()
    for part_name in parts_basic_info:
        basic_info = parts_basic_info[part_name]
        part_status = check_part(part_name, basic_info, project_modified_files, args)
        innerapi_change_status.update({part_name:part_status.__dict__})
    return innerapi_change_status

